package com.ruoyi.canteen.controller.v1;

import com.alibaba.fastjson.JSONObject;
import com.auth0.jwt.interfaces.Claim;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.JsonObject;
import com.ruoyi.canteen.constant.CpStatus;
import com.ruoyi.canteen.constant.OrderType;
import com.ruoyi.canteen.domain.*;
import com.ruoyi.canteen.service.*;
import com.ruoyi.canteen.service.impl.CanteenCpOrderServiceImpl;
import com.ruoyi.canteen.utils.JwtToken;
import com.ruoyi.canteen.vo.*;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.*;

/**
 * @Author Ryan
 * @Date 2021/9/20 21:10
 * @Version 1.0
 */
@RestController
@RequestMapping("/v1/order")
public class OrderApiController extends BaseController {

    private static final Logger log = LoggerFactory.getLogger(OrderApiController.class);

    @Autowired
    private ICanteenCpOrderService canteenCpOrderService;

    @Autowired
    private ICanteenCpOrderDetailService canteenCpOrderDetailService;

    @Autowired
    private ICanteenCpOrderLogService canteenCpOrderLogService;

    @Autowired
    private ICanteenCpService canteenCpService;

    @Autowired
    private ICanteenUserService canteenUserService;

    @Autowired
    private FeiePrintService feiePrintService;

    @Autowired
    private ICanteenCpOrderReturnService canteenCpOrderReturnService;


    /**
     * 查询当前用户所有订单列表
     */
    @GetMapping("/listByUser/{token}")
    public AjaxResult listByUser(@PathVariable("token") String token)
    {
        Optional<Map<String, Claim>> optionalMap = JwtToken.getClaims(token);
        if(optionalMap.isPresent()) {
            Map<String, Claim> map = optionalMap.get();
            Long uid = map.get("uid").asLong();
            // 已支付
            String payFlag = "1";
//            String payFlag = "0";
            List<OrderShowVo> list = canteenCpOrderService.selectOrderShowVoList(uid, payFlag);
            Map<Long, List<CanteenOrderItemVo>> orderItemMap = new HashMap<>();
            for (OrderShowVo curOrder : list) {
                List<CanteenOrderItemVo> itemVos =
                        canteenCpOrderDetailService.selectOrderDetailListByOrderId(curOrder.getOrderId());
                orderItemMap.put(curOrder.getOrderId(), itemVos);
            }
            return AjaxResult.success(new OrderAndItemListVo(list, orderItemMap));
        }else{
            return AjaxResult.error("登录信息失效，请先登录");
        }
    }

    /**
     * 默认获取用户有效订单
     * 已支付 + 最近三天
     * @param token
     * @return
     */
    @GetMapping("/listDefaultByUser/{token}")
    public AjaxResult listDefaultByUser(@PathVariable("token") String token)
    {
        Optional<Map<String, Claim>> optionalMap = JwtToken.getClaims(token);
        if(optionalMap.isPresent()) {
            Map<String, Claim> map = optionalMap.get();
            Long uid = map.get("uid").asLong();
            // 已支付
            String payFlag = "1";
            List<OrderShowVo> list = canteenCpOrderService.selectDefaultOrderShowVoList(uid, payFlag, 7);
//            List<OrderShowVo> list = canteenCpOrderService.selectDefaultOrderShowVoList(uid, payFlag, 200);
            Map<Long, List<CanteenOrderItemVo>> orderItemMap = new HashMap<>();
            for (OrderShowVo curOrder : list) {
                List<CanteenOrderItemVo> itemVos =
                        canteenCpOrderDetailService.selectOrderDetailListByOrderId(curOrder.getOrderId());
                orderItemMap.put(curOrder.getOrderId(), itemVos);
            }
            return AjaxResult.success(new OrderAndItemListVo(list, orderItemMap));
        }else{
            return AjaxResult.error("登录信息失效，请先登录");
        }
    }

    /**
     * 用户下单
     * @param canteenOrderVo 订单Vo对象
     * @return
     * @throws JsonProcessingException
     */
    @PostMapping("/add")
    public AjaxResult add(@RequestBody CanteenOrderVo canteenOrderVo) throws JsonProcessingException {
        String token  = canteenOrderVo.getToken();
        Optional<Map<String, Claim>> optionalMap = JwtToken.getClaims(token);
        if(optionalMap.isPresent()) {
            Map<String, Claim> map = optionalMap.get();
            Long uid = map.get("uid").asLong();
            int result = 0;
            if(canteenOrderVo.getItems().size() > 0){
                Map verifyCpStatusMap = verifyCpStatus(canteenOrderVo.getItems());
                if(verifyCpStatusMap.get("cpStatus").equals(false)){
                    List<CanteenOrderItemVo> invalidCpList =
                            (List<CanteenOrderItemVo>)verifyCpStatusMap.get("invalidCpList");
                    String cpList = "";
                    for(CanteenOrderItemVo itemVo : invalidCpList){
                        cpList = cpList + itemVo.getName() + ";";
                    }
                    cpList = cpList + "请删除后重新下单。";
                    // 验证不通过
                    return AjaxResult.error("订单中有失效菜品:" + cpList);
                }else{
                    canteenOrderVo.setUserId(uid);
                    if(canteenOrderVo.getOrderType().equals("2")){
                        // 现场点餐
                        canteenOrderVo.setOrderType(OrderType.ORDER_TYPE_HALL.toString());
                    }else{
                        // 默认普通线上点餐
                        canteenOrderVo.setOrderType(OrderType.ORDER_TYPE_NORMAL.toString());
                    }
                    canteenOrderVo.setSended(OrderType.ORDER_SENDED_WSD.toString());
                    // 默认未付款
                    canteenOrderVo.setPayFlag(OrderType.ORDER_PAYFLAG_WZF.toString());
                    // 默认0未付款，1、已付款；2、制作中；3、配送中；
                    canteenOrderVo.setOrderStatus(0);
                    // TODO 送餐信息保存至订单表
                    // 验证所有菜品对应门店ID是否一致
                    List<CanteenOrderItemVo> orderItems = canteenOrderVo.getItems();
                    String firstMdId = orderItems.get(0).getMdId();
                    boolean isSameMdId = true;
                    for(CanteenOrderItemVo vo : orderItems){
                        if(!firstMdId.equals(vo.getMdId())){
                            isSameMdId = false;
                        }
                    }
                    if(isSameMdId == false){
                        log.info(uid.toString() + "用户下单失败，菜品不属于同一门店----：" + canteenOrderVo.toString());
                        return AjaxResult.error("订单中含有不同食堂菜品");
                    }
                    canteenOrderVo.setMdId(Long.valueOf(firstMdId));
                    log.info(uid.toString() + "用户开始下单----：" + canteenOrderVo.toString());
                    try{
                        CanteenCpOrder cpOrder = canteenCpOrderService.newCanteenCpOrder(canteenOrderVo);
                        if(cpOrder == null){
                            log.error(uid.toString() + "用户下单失败-----：cpOrder为空,具体查看日志！");
                            return AjaxResult.error("价格变动，请清空购物车，重新下单！");
                        }else {
                            OrderResultVo finishOrder = canteenCpOrderService.convertCpOrderToVo(cpOrder);
                            log.info(uid.toString() + "用户下单完成-----：" + finishOrder.toString());
                            return AjaxResult.success(finishOrder);
                        }
                    }catch (Exception ex){
                        log.info(uid.toString() + "用户下单失败-----：" + ex.toString());
                        return AjaxResult.error(ex.getMessage());
                    }
                }
            }else {
                return AjaxResult.error("无效订单");
            }
        }else{
            log.warn("用户下单鉴权失败----：", canteenOrderVo.toString());
            return AjaxResult.error("登录信息失效，请先登录");
        }
    }

    /**
     * 验证菜品状态是否有效
     * @param items
     * @return
     */
    private Map verifyCpStatus(List<CanteenOrderItemVo> items){
        // 菜品状态默认:都为有效
        Boolean cpStatus = true;
        List<CanteenOrderItemVo> invalidCpList = new ArrayList<CanteenOrderItemVo>();
        for(CanteenOrderItemVo cp : items){
            // 查询下当前菜品状态是否为上架
            CanteenCp dbCp =  canteenCpService.selectCanteenCpById(cp.getId());
            if((dbCp.getDeleteFlag() == null) || (dbCp.getDeleteFlag().intValue() == CpStatus.CP_DELETE_Y)){
                // 删除状态，则加入无效菜单列表
                invalidCpList.add(cp);
            }else{
                if(dbCp.getStatus().intValue() != CpStatus.CP_STATUS_SJ){
                    // 非上架状态，则加入无效菜单列表
                    invalidCpList.add(cp);
                }
            }
        }
        if(invalidCpList.size() > 0){
            cpStatus = false;
        }
        Map<String, Object> reMap = new HashMap<String, Object>();
        reMap.put("cpStatus", cpStatus);
        reMap.put("invalidCpList", invalidCpList);
        return reMap;
    }


    /**
     * 获取本人单张订单详细信息
     */
    @GetMapping(value = "/getInfo")
    public AjaxResult getInfo(@RequestParam("token") String token, @RequestParam("id") Long id)
    {
        Optional<Map<String, Claim>> optionalMap = JwtToken.getClaims(token);
        if(optionalMap.isPresent()) {
            Map<String, Claim> map = optionalMap.get();
            Long uid = map.get("uid").asLong();

            OrderShowVo orderShowVo = canteenCpOrderService.selectOrderShowVo(uid, id);
            List<CanteenOrderItemVo> itemVos =
                    canteenCpOrderDetailService.selectOrderDetailListByOrderId(id);
            return AjaxResult.success(new OrderAndItemVo(orderShowVo, itemVos));
        }else{
            return AjaxResult.error("授权失败,重新进入");
        }
    }

    /**
     * 退费人获取单张订单详细信息
     */
    @GetMapping(value = "/getInfoByReturn")
    public AjaxResult getInfoByReturn(@RequestParam("token") String token, @RequestParam("orderId") Long orderId)
    {
        Optional<Map<String, Claim>> optionalMap = JwtToken.getClaims(token);
        if(optionalMap.isPresent()) {
            Map<String, Claim> map = optionalMap.get();
            Long uid = map.get("uid").asLong();
            CanteenUser curUser = canteenUserService.selectCanteenUserById(uid.toString());
            OrderShowVo orderShowVo = canteenCpOrderService.selectOrderShowByOrderId(orderId);
            if(curUser.getAuthCode().contains(orderShowVo.getMdId().toString())){
                return AjaxResult.success(orderShowVo);
            }else {
                return AjaxResult.error("授权失败");
            }
        }else{
            return AjaxResult.error("授权失败,重新进入");
        }
    }

    /**
     * 微卡-确认支付（更新订单支付状态）
     * @param payVo 确认VO对象信息：用户id + 订单id
     * @return
     */
    @PostMapping(value = "/confirmPay")
    public AjaxResult confirmPay(@RequestBody PayVo payVo){
        String token = payVo.getToken();
        String orderId = payVo.getOrderId();
        Optional<Map<String, Claim>> optionalMap = JwtToken.getClaims(token);
        if(optionalMap.isPresent()) {
            Map<String, Claim> map = optionalMap.get();
            Long uid = map.get("uid").asLong();
            int result = canteenCpOrderService.confirmPayById(uid, Long.valueOf(orderId));
            return AjaxResult.success(result);
        }else{
            return AjaxResult.error("授权失败,重新进入");
        }
    }

    /**
     * 微信-确认支付后（写入微信支付日志；调用小票打印机）
     * @param jsonParam 微信支付反馈json 参数值
     * @return
     */
    @PostMapping(value = "/confirmPayByWx")
    public AjaxResult confirmPayByWx(@RequestBody JSONObject jsonParam){
        String data = jsonParam.getString("data");
        JSONObject dataObj = jsonParam.getJSONObject("data");
        logger.info(jsonParam.toJSONString());
        // 写入日志表
        CanteenCpOrderLog canteenCpOrderLog = new CanteenCpOrderLog();
        canteenCpOrderLog.setLogType(Long.valueOf(2));
        canteenCpOrderLog.setOrderNo(dataObj.getString("outTradeNo"));
        canteenCpOrderLog.setLogContent(data);
        canteenCpOrderLog.setOperator("wxpaybak");
        canteenCpOrderLog.setLogTime(new Date());
        canteenCpOrderLogService.insertCanteenCpOrderLog(canteenCpOrderLog);
        if(!StringUtils.isEmpty(data)) {
            int result = canteenCpOrderService.confirmPayByOpenId(
                    dataObj.getJSONObject("userInfo").get("openId").toString(),
                    dataObj.get("outTradeNo").toString(), dataObj.get("transactionId").toString());

            if(feiePrintService.printOrder(dataObj.getString("outTradeNo"))){
                // 正常打印
            }else{
                // 异常打印，日志输出及推送提醒
            }
            return AjaxResult.success(result);
        }else{
            return AjaxResult.error("授权失败,重新进入");
        }
    }


    /**
     * 用户发起-取消订单申请
     * @param orderReturnVo 申请退款Vo
     * token     取消人token
     * orderId   订单id
     * reasonId  取消原因id
     * @return
     */
    @PostMapping(value = "/applyOrderCancel")
    public AjaxResult applyOrderCancel(@RequestBody OrderReturnVo orderReturnVo)
    {
        // 验证orderReturnVo中数据
        String token = orderReturnVo.getToken();
        String orderId = orderReturnVo.getOrderId();
        Integer reasonId = orderReturnVo.getReasonId();
        Optional<Map<String, Claim>> optionalMap = JwtToken.getClaims(token);
        if(optionalMap.isPresent()) {
            Map<String, Claim> map = optionalMap.get();
            Long uid = map.get("uid").asLong();
            // 1. 验证订单状态是否为已完成 5：已完成
            CanteenCpOrder curOrder =
                    canteenCpOrderService.selectCanteenCpOrderById(Long.valueOf(orderId));
            Integer mdId = curOrder.getMdId().intValue();
            // TODO 判断是否为当天订单，当天订单才可退款
            if(!DateUtils.getDate().equals(DateUtils.dateTime(curOrder.getCreateTime()))){
                return AjaxResult.error("非当日订单");
            }
            // TODO 判断订单id 在退单表中已存在
            CanteenCpOrderReturn canteenCpOrderReturn = new CanteenCpOrderReturn();
            canteenCpOrderReturn.setOrderId(Long.valueOf(orderId));
            List<CanteenCpOrderReturn> list =
                    canteenCpOrderReturnService.selectCanteenCpOrderReturnList(canteenCpOrderReturn);
            if(list.size() > 0){
                return AjaxResult.error("请不要重复申请");
            }
            if(curOrder.getOrderStatus().toString().equals("5") && curOrder.getUserId().equals(uid)){
                // 2. 更新订单状态为 6-售后中（退货申请待审核）2. 插入退款申请记录表
                int result = canteenCpOrderService.canncelOrderById(uid, Long.valueOf(orderId),
                        reasonId, mdId);
                if(result > 0){
                    return AjaxResult.success("申请已受理");
                }else{
                    return AjaxResult.error("申请失败");
                }
            }else {
                return AjaxResult.error("订单状态有误");
            }
        }else{
            return AjaxResult.error("申请失败,请重试");
        }
    }

}
